package com.ctrip.corp.obt.shard.sql.mybatis.interceptor.dialect;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.ctrip.corp.obt.generic.utils.StringPool;
import com.ctrip.corp.obt.shard.constants.DbType;
import com.ctrip.corp.obt.shard.domain.dbmetainfo.DatabaseMetaInfo;
import com.ctrip.corp.obt.shard.holder.ShardSourceHolder;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.compatibility.dm.DMFunctionCompatibility;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.compatibility.dm.DMSemanticCompatibility;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;

import com.ctrip.corp.obt.shard.utils.PluginUtils;

import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.SelectItem;
import org.springframework.stereotype.Component;

/**
 * @author x.shen
 * @desc KingBase方言类，用于实现语法兼容
 * @since 2023/11/1
 */
@Slf4j
@Component
public class DmDialect implements IDialect {

    /**
     * 语义兼容
     */
    private final DMSemanticCompatibility semanticCompatibility;
    /**
     * 函数兼容
     */
    private final DMFunctionCompatibility functionCompatibility;

    public DmDialect() {
        this.semanticCompatibility = new DMSemanticCompatibility();
        this.functionCompatibility = new DMFunctionCompatibility();
    }

    @Override
    public PageDialectModel buildPaginationSql(String originalSql, long offset, long limit) {
        StringBuilder sql = new StringBuilder(originalSql).append(" LIMIT ").append(FIRST_MARK);
        if (offset != 0L) {
            sql.append(StringPool.COMMA).append(SECOND_MARK);
            return new PageDialectModel(sql.toString(), offset, limit).setConsumerChain();
        } else {
            return new PageDialectModel(sql.toString(), limit).setConsumer(true);
        }
    }

    @Override
    public String buildTableSearchSql(String tableName) {
        return null;
    }

    /**
     * 前置全局处理，主要对引号等共性问题的处理
     *
     * @param sql
     * @return
     */
    @Override
    public String preHandleSql(String sql) {
        return semanticCompatibility.preHandleSql(sql);
    }

    @Override
    public void handleAsAlias(Alias alias) {
        semanticCompatibility.handleAsAlias(alias);
    }

    @Override
    public void handleColumnType(Column leftExpression, Expression rightExpression) {
        Map<DbType, DatabaseMetaInfo> xcDatabaseMetaInfoCache = ShardSourceHolder.getXcDatabaseMetaInfoCache();
        // 获取字段类型元信息
        DatabaseMetaInfo databaseMetaInfo = xcDatabaseMetaInfoCache.get(DbType.DM);
        if (Objects.isNull(databaseMetaInfo)) {
            return;
        }

        semanticCompatibility.handleColumnType(leftExpression, rightExpression,
            databaseMetaInfo.getColumnWithTypeMap());
    }

    /**
     * 处理关键字
     *
     * @param expression
     */
    @Override
    public void handleKeyword(Expression expression) {
        semanticCompatibility.handleKeyWords(expression, DMSemanticCompatibility.SQL_KEY_WORDS);
    }

    /**
     * 函数处理
     *
     * @param expression
     */
    @Override
    public void handleFunction(Function expression) {
        // 通用函数处理
        functionCompatibility.handleCommonFunction(expression, DMFunctionCompatibility.SQL_COMMON_FUNCTION_MAP);
        // 特殊函数处理
        functionCompatibility.handleSpecialFunction(expression);
    }

    @Override
    public Expression handleGroupConcat(Expression expression) {
        return functionCompatibility.handleGroupConcat(expression);
    }

    @Override
    public void handleInsertPrimaryKey(Insert insert, PluginUtils.DSBoundSql boundSql) {
        semanticCompatibility.handleInsertPrimaryKey(insert, boundSql);
    }

    /**
     * dm 处理主键id的逻辑，剔除 update set id = id 、set id = null
     * 
     * @param column
     * @param expression
     * @return
     */
    @Override
    public boolean handleUpdatePrimaryKey(Column column, Expression expression) {
        return semanticCompatibility.handleUpdatePrimaryKey(column, expression);
    }

    /**
     * 处理 select distinct 与 order by
     * ORDER BY项不在DISTINCT查询项中的问题
     *
     * @param needAddColumnList
     * @param selectItemsList
     */
    @Override
    public void handleOrderByWithDistinct(List<Column> needAddColumnList, List<SelectItem> selectItemsList) {
        semanticCompatibility.handleOrderByWithDistinct(needAddColumnList, selectItemsList);
    }
}
